home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / t3_1 / risc_src.lha / risc_sources / sys / OLDGC / gc.t < prev   
Encoding:
Text File  |  1990-06-13  |  21.4 KB  |  573 lines

  1. (herald gc
  2.   (env tsys
  3.        (osys table)       ;; %TABLE-VECTOR must be integrated here
  4.        (osys gc_weak)))   ;; for the GC-WEAK-???-LISTs
  5.  
  6. ;;; Copyright (c) 1985 Yale University
  7. ;;;     Authors: N Adams, R Kelsey, D Kranz, J Philbin, J Rees.
  8. ;;; This material was developed by the T Project at the Yale University Computer 
  9. ;;; Science Department.  Permission to copy this software, to redistribute it, 
  10. ;;; and to use it for any purpose is granted, subject to the following restric-
  11. ;;; tions and understandings.
  12. ;;; 1. Any copy made of this software must include this copyright notice in full.
  13. ;;; 2. Users of this software agree to make their best efforts (a) to return
  14. ;;;    to the T Project at Yale any improvements or extensions that they make,
  15. ;;;    so that these may be included in future releases; and (b) to inform
  16. ;;;    the T Project of noteworthy uses of this software.
  17. ;;; 3. All materials developed as a consequence of the use of this software
  18. ;;;    shall duly acknowledge such use, in accordance with the usual standards
  19. ;;;    of acknowledging credit in academic research.
  20. ;;; 4. Yale has made no warrantee or representation that the operation of
  21. ;;;    this software will be error-free, and Yale is under no obligation to
  22. ;;;    provide any services, by way of maintenance, update, or otherwise.
  23. ;;; 5. In conjunction with products arising from the use of this material,
  24. ;;;    there shall be no use of the name of the Yale University nor of any
  25. ;;;    adaptation thereof in any advertising, promotional, or sales literature
  26. ;;;    without prior written consent from Yale in each case.
  27. ;;;
  28.  
  29. ;;; T 3.0 garbage collector, based on Clark's algorithm.
  30. ;;; Tested using a simulated memory.  See GCTEST.T, GCSIM.T, etc.
  31. ;;;
  32. ;;; For a description of the algorithm and related information see
  33. ;;; GC.DOC. For a description of T3 data representations see DATA.DOC.
  34. ;;;
  35. ;;; ***Important***
  36. ;;;    The first two slots in a closure cannot contain closure
  37. ;;;    internal closures.  There cannot be pointers into either
  38. ;;;    of the first two slots of any extend that contains pointers.
  39. ;;;    This is because those slots are used to hold back pointers
  40. ;;;    during GC.
  41. ;;;
  42. ;;; The following procedures are needed for MOVE-OBJECT to run:
  43. ;;;
  44. ;;;    (K-LIST)
  45. ;;;        A global variable that cannot be a variable because of circularity
  46. ;;;        problems.  This is a list of unfinished objects, linked in a list
  47. ;;;        in the old heap.  It is a pseudonym for (SYSTEM-GLOBAL SLINK/K-LIST).
  48. ;;;    (DESCRIPTOR->FIXNUM pointer)
  49. ;;;        Change a descriptor to a fixnum by clobbering the tag.
  50. ;;;    (DESCRIPTOR-TAG pointer)
  51. ;;;        Returns the type tag of POINTER.
  52. ;;;    (CLOSURE? obj)
  53. ;;;        Is OBJ a closure?
  54. ;;;    (TEMPLATE-HEADER? header)
  55. ;;;        Is HEADER the header of a template?
  56. ;;;    (EXTEND-ELT extend offset)
  57. ;;;        The contents of EXTEND + OFFSET(in zero based longwords).  This is
  58. ;;;        settable.
  59. ;;;    (EXTEND-HEADER extend)
  60. ;;;        Returns the header of EXTEND i.e. (EXTEND-ELT EXTEND -1)
  61. ;;;    (HEADER-TYPE header)
  62. ;;;        The type field of an extend header.
  63. ;;;    (MAKE-POINTER pointer offset)
  64. ;;;        Returns a pointer to POINTER + OFFSET.
  65. ;;;    (GC-EXTEND->PAIR extend)
  66. ;;;    (GC-PAIR->EXTEND pair)
  67. ;;;        Change the type tag as indicated.
  68. ;;;    *OLD-SPACE-BEGIN*
  69. ;;;    *OLD-SPACE-FRONTIER*
  70. ;;;        The limits of old-space (these are fixnums).
  71. ;;;    (IN-NEW-SPACE? obj)
  72. ;;;        Is OBJ within new-space.
  73. ;;;    (CLOSURE-ENCLOSING-OBJECT <closure-pointer>)
  74. ;;;    (CLOSURE-ENCLOSER-OFFSET  <closure-pointer>)
  75. ;;;    (TEMPLATE-ENCLOSING-OBJECT <template-pointer>)  
  76. ;;;    (TEMPLATE-ENCLOSER-OFFSET  <template-pointer>)      
  77. ;;;    (TEMPLATE-POINTER-SLOTS    <template-pointer>)        
  78. ;;;    (TEMPLATE-SCRATCH-SLOTS    <template-pointer>)        
  79. ;;;    (TEMPLATE-INTERNAL-BIT?    <template-pointer>)        
  80. ;;;    HEADER/...
  81. ;;;
  82. ;;;      Simulator procedures that must shadow definitions in this file:
  83. ;;;    K-LIST
  84. ;;;        
  85. ;;;    (GC-COPY-PAIR pair) 
  86. ;;;        Copies PAIR into new space, putting a forwarding pointer in the cdr.
  87. ;;;    (GC-COPY-EXTEND obj size)
  88. ;;;        Copies an extend into new space.  OBJ is the extend, SIZE is the
  89. ;;;        length.  A forwarding pointer is put in the header of OBJ.
  90. ;;;    (GC-ERROR-MESSAGE string loc)
  91. ;;;        Print an error message.
  92. ;;;
  93. ;;;      Simulator procedures that must shadow definitions in T system:
  94. ;;;    CAR, CDR, LIST?, EXTEND?, VECTOR-LENGTH, NULL?,
  95. ;;;    IMMEDIATE?, TEMPLATE?, BYTEV?, BYTEV-LENGTH?
  96.  
  97. ;;; 3/14/86:
  98. ;;;  Flushed statistics other than the object count.
  99. ;;;  MOVE-OBJECT does the range check before anything else.
  100. ;;;  Old-space limits are in variables and not in a structure.
  101.  
  102. ;;; To do:
  103. ;;;  Vcells and weaks flushed in favor of weak-sets, weak-alists and
  104. ;;;    weak-tables.
  105.  
  106. ;;;   The top level procedure.  O-LOC is an extend containing a pointer to the
  107. ;;; object to be copied.  This is overwritten by a pointer to the new copy.
  108. ;;;   This procedure dispatches on the tag.  Nonpointers and nonrelocating
  109. ;;; pointers are left alone.  Pairs are checked to see if the cdr contains a
  110. ;;; forwarding pointer.  Extends require further dispatch.  The M68000 requires
  111. ;;; the TEMPLATE-HEADER? check first since the other extend tests are not
  112. ;;; valid on templates.  Extends are then checked for a forwarding pointer.
  113.  
  114. (define (move-object o-loc)
  115.   (let* ((obj (extend-header o-loc))
  116.          (fxobj (descriptor->fixnum obj)))
  117.     (if (not (and (fx>= fxobj (system-global slink/old-space-begin))
  118.                   (fx< fxobj (system-global slink/old-space-frontier))))
  119.         (pop-k-list)
  120.         (xselect (descriptor-tag obj)
  121.           ((tag/fixnum tag/immediate)
  122.            (pop-k-list))
  123.           ((tag/pair)
  124.            (cond ((and (list? (cdr obj)) ; This is a safety check
  125.                        (in-new-space? (cdr obj)))
  126.                   (set (extend-header o-loc) (cdr obj))
  127.                   (pop-k-list))
  128.                  (else
  129.                   (move-pair obj o-loc))))
  130.           ((tag/extend)
  131.            (let ((header (extend-header obj)))
  132.              (cond ((template-header? header)   ; 68000 requires this first
  133.                     (move-template obj o-loc))
  134.                    ((extend? header)
  135.                     (cond ((in-new-space? header)
  136.                            (set (extend-header o-loc) (extend-header obj))
  137.                            (pop-k-list))
  138.                           ((template? header)
  139.                            (move-closure obj o-loc))
  140.                           (else
  141.                            (gc-error-message "header is a non-template extend" o-loc)
  142.                            (pop-k-list))))
  143.                    ((immediate? header)
  144.                     (move-immediate-object obj o-loc))
  145.                    (else
  146.                     (gc-error-message "corrupt header" o-loc)
  147.                     (pop-k-list)))))))))
  148.  
  149. (define (move-frame-header o-loc)
  150.   (let* ((obj (frame-header o-loc))
  151.          (fxobj (descriptor->fixnum obj)))
  152.     (if (not (and (fx>= fxobj (system-global slink/old-space-begin))
  153.                   (fx< fxobj (system-global slink/old-space-frontier))))
  154.         (pop-k-list)
  155.     (move-template obj o-loc))))
  156.  
  157. ;;;   The K-LIST is a list of partially copied objects that are linked together
  158. ;;; in old space.  This cannot be a normal global variable as the GC would
  159. ;;; attempt to move it into new space.
  160.  
  161. (define-constant k-list
  162.   (object (lambda ()
  163.             (system-global slink/k-list))
  164.     ((setter self)
  165.      (lambda (k)
  166.        (set (system-global slink/k-list) k)))))
  167.  
  168. ;;;   Pop the next thing off the list and move it.  If it is a pair,
  169. ;;; remove it from the K-list and call MOVE-OBJECT to copy the cdr.
  170. ;;; Otherwise, (extend-elt K 1) contains the index of the next pointer
  171. ;;; to be copied. If there are none to be copied then remove the
  172. ;;; extend from the K-list and recur; otherwise, decrement the
  173. ;;; pointer and call MOVE-OBJECT to do the copying.
  174.  
  175. (define (pop-k-list)
  176.   (let ((next (k-list)))
  177.     (cond ((null? next)
  178.            '#t)   ; The only (non-error) return in the GC.
  179.           ((list? next)
  180.            (let* ((fwd (cdr next))
  181.                   (to-copy (if (list? fwd) (gc-pair->extend fwd) fwd)))
  182.              (set (k-list) (car next))
  183.              (move-object (make-pointer to-copy 0))))
  184.           ((fx< (extend-elt next 1) 0)
  185.            (set (k-list) (extend-elt next 0))
  186.            (pop-k-list))
  187.           (else
  188.            (let ((offset (fx- (extend-elt next 1) 1))
  189.                  (forward (extend-header next)))
  190.              (set (extend-elt next 1) offset)
  191.              (move-object (make-pointer forward offset)))))))
  192.  
  193. ;;;   Forward OBJ using copy-pair.  Push the old pair onto the k-list.
  194. ;;; Set the contents of O-LOC to the forwarded pair.  Then recursively
  195. ;;; move the car of the forwarded pair The object in the cdr will
  196. ;;; be moved when the k-list is popped.
  197.  
  198. (define (move-pair obj o-loc)
  199.   (let* ((new (gc-copy-pair obj))
  200.          (xnew (gc-pair->extend new)))
  201.     (set (car obj) (k-list))
  202.     (set (k-list) obj)
  203.     (set (extend-header o-loc) new)
  204.     (move-object xnew)))
  205.  
  206. ;;;   Forward OBJ which is an extend of SIZE longwords with NDESC
  207. ;;; descriptor slots. (Note: Descriptor slots are always the first
  208. ;;; slots of an extend.) O-LOC is the location into which the descriptor
  209. ;;; (+ FORWARDED-OBJECT E-OFF) should be stored.
  210. ;;;   OBJ is forwarded by the primitive COPY-EXTEND which copies the
  211. ;;; old object into the new area.  A forwarding pointer is put in the
  212. ;;; header of the old object.
  213. ;;;   If there are zero descriptors pop the k list.  If there is a
  214. ;;; single descriptor, move it.  If there is more than one descriptor,
  215. ;;; link the object into the K-list, put the number of addresses
  216. ;;; into (extend-elt obj 2), and move the first address.  Closures with
  217. ;;; only one slot are treated as pairs.
  218.  
  219. (define (move-extend obj size ndesc o-loc e-off)
  220.   (let ((new (gc-copy-extend obj size)))
  221.     (set (extend-header o-loc) (make-pointer new e-off))
  222.     (cond ((fx> ndesc 1)
  223.            ;; Push obj onto K list, and set slot-offset.
  224.            (set (extend-elt obj 0) (k-list))
  225.            (set (k-list) obj)
  226.            (let ((last-elt (fx- ndesc 1)))
  227.              (set (extend-elt obj 1) last-elt)
  228.              (move-object (make-pointer new last-elt))))
  229.           ((closure? new) ; OBJ's header is now a forwaring pointer.
  230.            (xcond ((fx= ndesc 0)
  231.                    (move-object new))
  232.                   ((fx= ndesc 1)
  233.                    (set (extend-elt obj 0) (k-list))
  234.                    (set (k-list) (gc-extend->pair obj))
  235.                    (move-object new))))
  236.           (else
  237.            (xcond ((fx= ndesc 0)
  238.                    (pop-k-list))
  239.                   ((fx= ndesc 1)
  240.                    (move-object (make-pointer new 0))))))))
  241.  
  242. ;;;   There are 3 types of templates: code vector, closure internal,
  243. ;;; and dynamic.  All templates are enclosed in other objects.
  244.  
  245. (define (move-template obj o-loc)
  246.   (let ((encloser (template-enclosing-object obj))
  247.         (offset   (template-encloser-offset  obj)))
  248.     (move-internal-object encloser (fx- offset 1) o-loc)))
  249.  
  250. ;;;   This procedure is only called on heap closures since stack closures
  251. ;;; are traced and not copied.  If the closure is internal to another object
  252. ;;; then the enclosing object is moved, otherwise, it is moved as a normal
  253. ;;; extend.
  254.  
  255. (define (move-closure obj o-loc)
  256.   (let ((template (extend-header obj)))
  257.     (cond ((template-internal-bit? template)
  258.            (let ((encloser  (closure-enclosing-object obj))
  259.                  (offset    (closure-encloser-offset obj)))
  260.              (move-internal-object encloser (fx- offset 1) o-loc)))
  261.           (else
  262.            (let* ((ptrs (template-pointer-slots template))
  263.                   (size (fx+ ptrs (template-scratch-slots template))))
  264.              (move-extend obj size ptrs o-loc -1))))))
  265.  
  266. ;;;   Move ENCLOSER which was traced through an internal pointer with an offset
  267. ;;; of OFFSET.  Dispatch on the location and type of ENCLOSER.
  268.  
  269. (define (move-internal-object encloser offset o-loc)
  270.   (let ((header (extend-header encloser)))
  271.     (cond ((and (extend? header)
  272.                 (in-new-space? header))
  273.            (set (extend-header o-loc) (make-pointer header offset))
  274.            (pop-k-list))
  275.           ((bytev? encloser)
  276.            (set (extend-header o-loc)
  277.                 (make-pointer (gc-copy-extend encloser (bytev-cells encloser))
  278.                               offset))
  279.            (pop-k-list))
  280.           ((unit? encloser)
  281.            (let ((size (unit-length encloser)))
  282.              (move-extend encloser size size o-loc offset)))
  283.           ((template? header)
  284.            (let* ((ptrs (template-pointer-slots header))
  285.                   (size (fx+ ptrs (template-scratch-slots header))))
  286.              (move-extend encloser size ptrs o-loc offset)))
  287.           (else
  288.            (gc-error-message "corrupt internal object" o-loc)
  289.            (pop-k-list)))))
  290.  
  291. ;;;   Find out whether a value has been copied into the new heap and return a
  292. ;;; a flag and the new location.  The flag is true if the object was indeed
  293. ;;; retained.  This is a simpler version of MOVE-OBJECT.  Symbols are always
  294. ;;; copied.
  295.  
  296. (define (get-new-copy obj)
  297.   (let ((fxobj (descriptor->fixnum obj)))
  298.     (if (not (and (fx>= fxobj (system-global slink/old-space-begin))
  299.                   (fx< fxobj (system-global slink/old-space-frontier))))
  300.         (return t obj)
  301.         (xselect (descriptor-tag obj)
  302.           ((tag/fixnum tag/immediate)
  303.            (return t obj))
  304.           ((tag/pair)
  305.            (if (and (list? (cdr obj))
  306.                     (in-new-space? (cdr obj)))
  307.                (return t (cdr obj))
  308.                (return nil nil)))
  309.           ((tag/extend)
  310.            (let ((header (extend-header obj)))
  311.               (cond ((extend? header)
  312.                      (get-new-extend-copy obj header))
  313.                     ((symbol? obj)
  314.                      (return t (gc-copy-object obj)))
  315.                     (else
  316.                      (return nil nil)))))))))
  317.  
  318. (define (get-new-extend-copy obj header)
  319.   (cond ((template-header? header)   ; 68000 requires this first
  320.          (receive (traced? new-loc)
  321.                   (get-new-copy (template-enclosing-object obj))
  322.            (if traced?
  323.                (return t (make-pointer new-loc
  324.                                        (fx- (template-encloser-offset obj) 1)))
  325.                (return nil nil))))
  326.         ((in-new-space? header)
  327.          (return t (extend-header obj)))
  328.         ((template-internal-bit? header)
  329.          (receive (traced? new-loc)
  330.                   (get-new-copy (closure-enclosing-object obj))
  331.            (if traced?
  332.                (return t (make-pointer new-loc
  333.                                         (fx- (closure-encloser-offset obj) 1)))
  334.                (return nil nil))))
  335.         (else
  336.          (return nil nil))))
  337.  
  338. ;;; Copy an object and return the new pointer
  339.  
  340. (define copy-object-cell
  341.   (make-vector 1))
  342.  
  343. (define (gc-copy-object thing)
  344.   (set (vref copy-object-cell 0) thing)
  345.   (move-object (make-pointer copy-object-cell 0))
  346.   (vref copy-object-cell 0))
  347.  
  348. ;;; Procedures for moving the immediate extends.
  349.  
  350. (define (move-error obj o-loc)
  351.   (ignore obj)
  352.   (gc-error-message "no method for an immediate" o-loc)
  353.   (pop-k-list))
  354.  
  355. (define (move-bytes obj o-loc)
  356.   (set (extend-header o-loc) (gc-copy-extend obj (bytev-cells obj)))
  357.   (pop-k-list))
  358.  
  359. (define (move-foreign obj o-loc)
  360.   (move-extend obj 2 1 o-loc -1))
  361.  
  362. (define (move-general-vector obj o-loc)
  363.   (let ((len (vector-length obj)))
  364.     (move-extend obj len len o-loc -1)))
  365.  
  366. (define (move-unit obj o-loc)
  367.   (let ((len (unit-length obj)))
  368.     (move-extend obj len len o-loc -1)))
  369.  
  370. (define (move-string-slice obj o-loc)
  371.   (move-extend obj 2 1 o-loc -1))
  372.  
  373. (define (move-cell obj o-loc)
  374.   (move-extend obj 1 1 o-loc -1))
  375.  
  376. ;;; Bignums contain only fixnums and thus do not need to be traced.
  377.  
  378. (define (move-bignum obj o-loc)
  379.   (set (extend-header o-loc) (gc-copy-extend obj (bignum-length obj)))
  380.   (pop-k-list))
  381.  
  382. ;;; Stacks must be scanned.
  383.  
  384. (define (move-stack obj o-loc)
  385.   (let ((new (gc-copy-extend obj (stack-length obj))))
  386.     (set (extend-header o-loc) new)
  387.     (scan-stack (make-pointer new 0)
  388.         (fx+ (descriptor->fixnum new)
  389.                     (fx- (stack-length new) 1)))
  390.     t)) ; GC returns from here if there were any stacks copied.
  391.  
  392. ;;; Floats
  393.  
  394. (define (move-double-float obj o-loc)
  395.   (set (extend-header o-loc)
  396.        (gc-copy-extend obj 2))
  397.   (pop-k-list))
  398.  
  399. (define (move-single-float obj o-loc)
  400.   (set (extend-header o-loc)
  401.        (gc-copy-extend obj 1))
  402.   (pop-k-list))
  403.                       
  404. (define (move-vcell obj o-loc)
  405.   (move-extend obj %%vcell-size %%vcell-size o-loc -1))
  406.  
  407. ;;; Weak sets
  408.  
  409. (define (bogus-move-weak-set obj o-loc)
  410.   (move-extend obj 1 1 o-loc -1))
  411.  
  412. (define (move-weak-set obj o-loc)
  413.   (cond ((weak-semaphore-set? obj)
  414.          (move-extend obj 1 1 o-loc -1))
  415.         (else
  416.          (let ((new (gc-copy-extend obj 1)))
  417.            (set (extend-header o-loc) new)
  418.            (set (extend-header new) (gc-weak-set-list))
  419.            (set (gc-weak-set-list) new)
  420.            (pop-k-list)))))
  421.  
  422. ;;; The code for weak alists is just like the code for weak sets.
  423.  
  424. (define (bogus-move-weak-alist obj o-loc)
  425.   (move-extend obj 1 1 o-loc -1))
  426.  
  427. (define (move-weak-alist obj o-loc)
  428.   (cond ((weak-semaphore-set? obj)
  429.          (move-extend obj 1 1 o-loc -1))
  430.         (else
  431.          (let ((new (gc-copy-extend obj 1)))
  432.            (set (extend-header o-loc) new)
  433.            (set (extend-header new) (gc-weak-alist-list))
  434.            (set (gc-weak-alist-list) new)
  435.            (pop-k-list)))))
  436.  
  437. ;;; Weak Tables
  438.  
  439. ;;; WEAK-TABLE-TABLE must be the first slot in a WEAK-TABLE
  440.  
  441. (define (bogus-move-table obj o-loc)
  442.   (move-extend obj 2 2 o-loc -1))
  443.  
  444. (define (move-weak-table obj o-loc)
  445.   (cond ((weak-semaphore-set? obj)
  446.          (move-extend obj 2 2 o-loc -1))
  447.         (else
  448.          (exchange (weak-table-vector obj)
  449.                    (%table-vector (weak-table-table obj)))
  450.          (let ((new (gc-copy-extend obj 2)))
  451.            (set (extend-header o-loc) new)
  452.            (set (extend-header new) (gc-weak-table-list))
  453.            (set (gc-weak-table-list) new)
  454.            (move-object (make-pointer new 0))))))
  455.  
  456. (define (move-weak-cell obj o-loc)
  457.   (set (weak-cell-contents obj) '#f)
  458.   (move-extend obj 1 1 o-loc -1))
  459.  
  460. ;;; Moving immediates
  461.  
  462. (define (move-immediate-object obj o-loc)
  463.   ((vref gc-dispatch-vector (header-type (extend-header obj)))
  464.    obj o-loc))
  465.  
  466. (define gc-dispatch-vector (make-vector %%number-of-immediate-types))
  467.  
  468. (let ((gc-copiers
  469.       `(
  470.         (,header/text           ,move-bytes)
  471.         (,header/general-vector ,move-general-vector)
  472.         (,header/unit           ,move-unit)
  473.         (,header/slice          ,move-string-slice)
  474.         (,header/symbol         ,move-bytes)
  475.         (,header/bytev          ,move-bytes)
  476.         (,header/foreign         ,move-foreign)
  477.         (,header/template       ,move-template)
  478.         (,header/cell           ,move-cell)
  479.         (,header/bignum         ,move-bignum)
  480.         (,header/stack          ,move-stack)
  481.         (,header/double-float   ,move-double-float)
  482.         (,header/single-float   ,move-single-float)
  483.         (,header/vcell          ,move-vcell)
  484.         (,header/weak-set       ,move-weak-set)
  485.         (,header/weak-alist     ,move-weak-alist)
  486.         (,header/weak-table     ,move-weak-table)
  487.         (,header/weak-cell      ,move-weak-cell)
  488.        ; (,header/task           ,move-error)
  489.        ; (,header/true           ,move-error)
  490.        ; (,header/char           ,move-error)
  491.        ; (,header/bitv           ,move-bitv)
  492.        ; (,header/vframe         ,move-error) only on stack
  493.        ; (,header/short-float    ,move-error) unimplemented
  494.         )))
  495.   (vector-fill gc-dispatch-vector move-error)
  496.   (walk (lambda (x) (set (vector-elt gc-dispatch-vector
  497.                                      (fixnum-ashr (car x) 2))
  498.                          (cadr x)))
  499.         gc-copiers))
  500.  
  501. ;;; Three little utilities.
  502. #|
  503. (define (gc-copy-pair pair)
  504.   (gc-count-message)
  505.   (let ((new (cons (car pair) (cdr pair))))
  506.     (set (cdr pair) new)
  507.     new))
  508.  
  509. (define (gc-copy-extend obj size)
  510.   (gc-count-message)
  511.   (let ((new (%make-extend (extend-header obj) size)))
  512.     (%copy-extend new obj size)
  513.     (set (extend-header obj) new)
  514.     new))
  515. |#
  516.  
  517. (define (gc-copy-pair pair)
  518.   (lap ()
  519.     (load l (d@nil slink/area-frontier) a2)
  520.     (add ($ 8) a2)
  521.     (store l a2 (d@nil slink/area-frontier))
  522.     (sub ($ 5) a2)
  523.     (load l (d@r a1 %%car) a4)
  524.     (store l a4 (d@r a2 %%car))
  525.     (load l (d@r a1 %%cdr) a4)
  526.     (store l a4 (d@r a2 %%cdr))
  527.     (store l a2 (d@r a1 %%cdr))
  528.     (jr link-reg)
  529.     (move a2 a1)))
  530.  
  531. (define (gc-copy-extend obj size)
  532.   (lap ()
  533.     (load l (d@nil slink/area-frontier) a3)
  534.     (add ($ 4) a3)
  535.     (add a2 a3 a4)
  536.     (store l a4 (d@nil slink/area-frontier))
  537.     (add ($ 2) a1 a2)
  538.     (sub ($ 2) a3 a1)
  539.     (load l (d@r a2 -4) a5)
  540.     (store l a5 (d@r a3 -4))
  541.     (store l a1 (d@r a2 -4))
  542.     (jbr copy-loop-top)
  543. copy-loop
  544.     (load l (d@r a2 0) a5)
  545.     (store l a5 (d@r a3 0))
  546.     (add ($ 4) a2)
  547.     (add ($ 4) a3)
  548. copy-loop-top
  549.     (j< a3 a4 copy-loop)
  550.     (jr link-reg)
  551.     (noop)))
  552.  
  553.  
  554. (define (bytev-cells bytev)
  555.   (fixnum-ashr (fx+ (bytev-length bytev) 3) 2))
  556.  
  557. ;;; Statistics and messages.
  558.  
  559. (lset *gc-object-count* 0)       ;;; objects copied up to last message
  560. (lset *gc-click* 0)              ;;; objects copied since last message
  561. (lset *gc-message-frequency* 10000)
  562.  
  563. (define (initialize-gc-stats)
  564.   (set *gc-click* 0)
  565.   (set *gc-object-count* 0))
  566.        
  567. (define-constant (gc-count-message)
  568.   (set *gc-click* (fx+ *gc-click* 1))
  569.   (cond ((fx>= *gc-click* *gc-message-frequency*)
  570.          (set *gc-object-count* (fx+ *gc-object-count* *gc-click*))
  571.          (set *gc-click* 0)    
  572.          (gc-message *gc-object-count*))))
  573.